package com.wg.neptune.proxy;


import com.wg.neptune.zookeeper.RegisterCenter;
import com.wg.neptune.cluster.Cluster;
import com.wg.neptune.cluster.ClusterEngine;
import com.wg.neptune.model.ProviderService;
import com.wg.neptune.model.RpcRequest;
import com.wg.neptune.netty.client.NettyClient;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;

/**
 * 代理工厂
 */
public class RevokerProxy implements InvocationHandler {

    private ExecutorService fixedThreadPool = null;

    //服务接口
    private Class<?> targetInterface;
    //超时时间
    private int consumeTimeout;
    //调用者线程数
    private static int threadWorkerNumber = 10;
    //负载均衡策略
    private String clusterStrategy;


    public RevokerProxy(Class<?> targetInterface, int consumeTimeout, String clusterStrategy) {
        this.targetInterface = targetInterface;
        this.consumeTimeout = consumeTimeout;
        this.clusterStrategy = clusterStrategy;
    }


    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //服务接口名称
        String serviceKey = targetInterface.getName();
        //获取某个接口的服务提供者列表
        RegisterCenter registerCenter = RegisterCenter.singleton();
        List<ProviderService> providerServices = registerCenter.getServiceMap4Consumer().get(serviceKey);
        //根据软负载策略,从服务提供者列表选取本次调用的服务提供者
        Cluster clusterStrategyService = ClusterEngine.getCluster(clusterStrategy);
        ProviderService providerService = clusterStrategyService.select(providerServices);
        //复制一份服务提供者信息
        ProviderService newProvider = providerService.copy();
        //设置本次调用服务的方法以及接口
        newProvider.setServiceMethod(method);
        newProvider.setServiceItf(targetInterface);

        //声明调用AresRequest对象,AresRequest表示发起一次调用所包含的信息
        final RpcRequest request = new RpcRequest();
        //设置本次调用的唯一标识
        request.setUniqueKey(UUID.randomUUID().toString() + "-" + Thread.currentThread().getId());
        //设置本次调用的服务提供者信息
        request.setProviderService(newProvider);
        //设置本次调用的超时时间
        request.setInvokeTimeout(consumeTimeout);
        //设置本次调用的方法名称
        request.setInvokedMethodName(method.getName());
        //设置本次调用的方法参数信息
        request.setArgs(args);

        //根据服务提供者的ip,port,构建InetSocketAddress对象,标识服务提供者地址
        String serverIp = request.getProviderService().getServerIp();
        int serverPort = request.getProviderService().getServerPort();
        InetSocketAddress inetSocketAddress = new InetSocketAddress(serverIp, serverPort);
        NettyClient.star(inetSocketAddress,request);
        return null;
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{targetInterface}, this);
    }


}
